package cn.cycleif.component.limit;

import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import cn.cycleif.exception.BaseException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

/**
 * &#064;Date: 24/06/16-18:23
 * &#064;Description: 限流切面
 */
@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class AccessLimitAspect {

  private final StringRedisTemplate redisTemplate;
  private final HttpServletRequest  request;

  @Before("@annotation(accessLimit)")
  public void doBefore(AccessLimit accessLimit) {
    int time = accessLimit.time();

    // redis key = IP + Api
    String key      = request.getRemoteAddr() + request.getRequestURL();
    String maxTimes = redisTemplate.opsForValue().get(key);
    if (maxTimes == null) {  // init
      redisTemplate.opsForValue().set(key, "1", time, accessLimit.unit());
      return;
    }
    int times = Integer.parseInt(maxTimes);
    if (times < accessLimit.count()) {
      redisTemplate.opsForValue().increment(key);
      redisTemplate.expire(key, time, accessLimit.unit());
    } else {
      log.info("API请求限流拦截启动,{} 请求过于频繁", key);
      throw new BaseException("请求过于频繁,稍后重试");
    }
  }
}
